<template>
    <div class="wvideo">
        <el-container>
            <el-main>
                <WebVideo :is-desktop="isDesktopStream" :user="user" :ref="(e) => {
                    if (!playerConfig[user]) {
                        playerConfig[user] = {};
                    }
                    playerConfig[user].playerRef = e as InstanceType<typeof WebVideo>;
                }" :click="play" :stream="playerConfig[user]?.stream" class="webVideo main-video" />
                <div class="msg-control">
                    <el-row justify="space-between" style="width: 100%;">
                        <el-col :span="15">
                            <el-input v-model="msg" maxlength="300" show-word-limit type="textarea" resize='none'
                                :rows="12" placeholder="输入内容" />
                            <!-- :autosize="{ minRows: 12, maxRows: 14 }"  -->
                        </el-col>
                        <el-col :span="6">
                            <el-tooltip class="box-item" effect="dark" content="房间地址" placement="top">
                                <el-input disabled v-model="path" maxlength="30" show-word-limit placeholder="输入地址" />
                            </el-tooltip>
                            <el-select v-model="selectUser" placeholder="全部" style="width: 100%;margin-top: 20px;">
                                <el-option :key="''" label="全部" :value="''" />
                                <el-option v-for="item in remotePlayerList" :label="item" :value="item" />
                            </el-select>
                            <el-button style="width: 100%;" type="success" plain @click="test">测试</el-button>
                        </el-col>
                        <el-col :span="2">
                            <el-button style="width: 100%;" type="success" plain @click="test">发送</el-button>
                            <div></div>
                            <el-switch v-model="isDesktopStream" active-text="切换摄像头" inactive-text="切换桌面"
                                inline-prompt />
                            <!-- <el-button style="width: 100%;margin-top: 20px;" type="success" plain @click="isDesktopStream = !isDesktopStream">连接</el-button> -->
                        </el-col>
                    </el-row>
                </div>

            </el-main>
            <el-aside class="contain-right">
                <el-scrollbar height="100%">
                    <WebVideo class="webVideo"
                    :is-desktop="playerConfig[item].isDesktopStream"
                        :ref="(e) => { if (playerConfig[item]) playerConfig[item].playerRef = e as InstanceType<typeof WebVideo> }"
                        v-for="(item, index) in Object.keys(playerConfig).filter(i => i !== user)" :user="item"
                        :stream="playerConfig[item].stream" />

                </el-scrollbar>
            </el-aside>
        </el-container>
    </div>
</template>
<script setup lang="ts">
import { MessageType, type MessageData } from '@/common/MessageData';
import { SignalingClient } from '@/common/SignalingClient';
import { WebRtc } from '@/common/WebRtc';
import WebVideo from '@/components/WebVideo.vue';
import { ElNotification } from 'element-plus';
import { nanoid } from 'nanoid';
import { computed, onMounted, onUnmounted, reactive, ref, watch } from 'vue';
import { useRoute } from 'vue-router';
const isDesktopStream = ref(false);
const route = useRoute();
const path = ref<string>('');
const user = ref<string>(nanoid(8));
let server: SignalingClient | undefined;
let webrtc: WebRtc | undefined;
const playerConfig = reactive<{
    [key: string]: {
        playerRef?: InstanceType<typeof WebVideo>,
        stream?: MediaStream | null,
        isDesktopStream?: boolean
    }
}>({})
const selectUser = ref('');
const remotePlayerList = computed(() => Object.keys(playerConfig).filter(e => e != user.value))
const msg = ref('');
const play = () => {
    console.log("点击播放");
    const pr = playerConfig[user.value]?.playerRef
    if (pr?.isPlayer) {
        stopWebrtc();
    } else {
        connection();
    }
}
watch(isDesktopStream, (v) => {
    const pr = playerConfig[user.value]?.playerRef
    if (pr?.isPlayer) {
        stopWebrtc();
        connection();
    }
})
const getStream = async () => {
    if (isDesktopStream.value) {
        return await navigator.mediaDevices.getDisplayMedia({
            audio: true, video: true
        });
    } else {
        return await navigator.mediaDevices.getUserMedia({
            audio: true, video: true
        });
    }
}
const connection = async () => {
    if (!server) {
        server = await init();
    }
    const localStream: MediaStream = await getStream();
    playerConfig[user.value].stream = localStream;
    webrtc = new WebRtc(localStream, server, (stream, id) => {
        //远程流
        console.log("处理远端流", id);
        playerConfig[id].stream = stream;
    })
    server.send({ sender: user.value, type: MessageType.ready,ext:{isDesktopStream:isDesktopStream.value} });

}
const init = async (): Promise<SignalingClient> => {
    if (server) {
        return server
    }
    server = new SignalingClient('ws://192.168.1.46:8080/ws', path.value, user.value)
    await server.connect()
    console.log("远程地址连接成功");
    server.onMessage((message) => {
        switch (message.type) {
            case MessageType.online: online(message); break
            case MessageType.close: offline(message.sender!); break
            case MessageType.ready: markCall(message); break
            case MessageType.offer: handleOffer(message); break
            case MessageType.answer: handleAnswer(message); break
            case MessageType.ice: handleICE(message); break
            case MessageType.bye: handleBye(message); break
            case MessageType.msg: handleMsg(message); break
        }
    })
    server.onClose((e) => {
        console.log("断开连接");
    })
    return server;
}
const handleMsg = (message: MessageData) => {
    console.log("发来消息");

    if (message.data) {
        ElNotification({
            title: `${message.sender}发来消息`,
            message: message.data,
            type: 'success',
        })
    }
}
const markCall = async (message: MessageData) => {
    if (playerConfig[user.value].stream && webrtc) {
        const pc = webrtc!.createPeerConnection(message.sender!)
        const offer = await pc.createOffer();
        await pc.setLocalDescription(offer);
        playerConfig[message.sender!].isDesktopStream=message.ext?.isDesktopStream;
        server!.send({ data: offer, to: message.sender, type: MessageType.offer,ext:{isDesktopStream:isDesktopStream.value} });
    }
}
const handleOffer = (message: MessageData) => {
    if (playerConfig[user.value].stream && webrtc) {
        webrtc.handleOffer(message)
        playerConfig[message.sender!].isDesktopStream=message.ext?.isDesktopStream;
    }
}
const handleAnswer = (message: MessageData) => {
    if (playerConfig[user.value].stream && webrtc) {
        webrtc.handleAnswer(message)
    }
}
const handleICE = (message: MessageData) => {
    if (playerConfig[user.value].stream && webrtc) {
        webrtc.handleICE(message)
    }
}
const handleBye = (message: MessageData) => {
    if (webrtc) {
        console.log("远端下线", message.sender);
        server?.delRemote(message.sender!)
        playerConfig[message.sender!].stream = null;
        playerConfig[message.sender!] = {};
    }
}
const online = (message: MessageData) => {
    const userList = message.data as string[];
    Object.keys(playerConfig).forEach(e => {
        if (!userList.includes(e)) {
            delete playerConfig[e];
        }
    })
    userList.forEach(e => {
        if (!playerConfig[e]) {
            ElNotification({
                title: '有人来了',
                message: `${e}上线了`,
                type: 'success',
            })
            playerConfig[e] = {};
        }
    })
}
const offline = (userId: string) => {
    delete playerConfig[userId]
    server?.delRemote(userId)
    ElNotification({
        title: '有人离开',
        message: `${userId}下线了`,
        type: 'info',
    })
}
onMounted(() => {
    path.value = route.params['address'] as string;
    init()
})
onUnmounted(() => {
    server?.close()
})

const stopWebrtc = () => {
    webrtc?.stop(user.value);
    playerConfig[user.value].stream = null;
    for (const key in playerConfig) {
        playerConfig[key].stream = null;
    }
}

const test = () => {
    if (server && msg.value) {
        console.log(user.value, "发送消息", playerConfig);
        server.send({ data: msg.value, to: selectUser.value })
        msg.value = ''
    }
}
</script>
<style scoped>
.webVideo {
    width: 100%;
    /* display: flex; */
    background-color: rgba(0, 0, 0, 0.233);
}

.main-video {
    height: 65%;
}

.wvideo {
    height: 100vh;
    width: 100vw;
    background-color: rgba(163, 247, 253, 0.76);
}

.contain-right {
    width: 30%;
    height: 100vh;
    padding: 20px 20px 20px 0px;
    /* background-color: aquamarine; */
}

.msg-control {
    width: 100%;
    height: 35%;
    display: flex;

    padding-top: 20px;
    padding-bottom: 20px;
}
</style>